package com.atao.baokede.service.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.atao.baokede.mapper.CartMapper;
import com.atao.baokede.mapper.ItemMapper;
import com.atao.baokede.pojo.*;
import com.atao.baokede.pojo.dto.ItemDto;
import com.atao.baokede.service.CartService;
import com.atao.baokede.service.ItemService;
import com.atao.baokede.service.MerchantService;
import com.atao.baokede.utils.ThreadLocalUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.atao.baokede.constant.ItemConstant.*;

@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private ItemMapper itemMapper;

    @Autowired
    private CartService cartService;
    @Autowired
    private CartMapper cartMapper;


    @Override
    public Item findById(Long id) {
        return itemMapper.findById(id);
    }

    @Override
    public PageBean<Item> findItemsByMerchantId(Integer pageNum, Integer pageSize) {
        PageBean<Item> pb = new PageBean<>();
        PageHelper.startPage(pageNum, pageSize);
        Map<String, Object> map = ThreadLocalUtil.getMerchant();
        Long merchantId = ((Number) map.get("id")).longValue();
        List<Item> items = itemMapper.findItemsByMerchantId(merchantId);
        //强转的原因：Page中提供了方法，可以获取总记录数和当前页数据
        Page<Item> p = (Page<Item>) items;
        //把数据填充到PageBean对象中
        pb.setTotal(p.getTotal());
        pb.setItems(p.getResult());
        return pb;
    }

    @Override
    public void addItem(ItemDto itemDto) throws IOException {
        // 补充item信息
        Map<String, Object> map = ThreadLocalUtil.getMerchant();
        Long merchantId = ((Number) map.get("id")).longValue();
        Item item = new Item();
        BeanUtil.copyProperties(itemDto, item);
        item.setMerchantId(merchantId);
        item.setSold(0L);
        item.setCommentCount(0L);
        item.setStatus(STATUS_AUDITING);

        itemMapper.addItem(item);
    }

    @Override
    public PageBean<Item> findAllActiveItems(Integer pageNum, Integer pageSize) {
        PageBean<Item> pb = new PageBean<>();
        PageHelper.startPage(pageNum, pageSize);
        List<Item> items = itemMapper.findAllActiveItems(STATUS_ON_SALE);
        //强转的原因：Page中提供了方法，可以获取总记录数和当前页数据
        Page<Item> p = (Page<Item>) items;
        //把数据填充到PageBean对象中
        pb.setTotal(p.getTotal());
        pb.setItems(p.getResult());
        return pb;
    }

    @Override
    public Map<String, Object> searchItems(String keyword, String searchAfter, String direction, int size) throws IOException {
        SearchRequest request = new SearchRequest("items");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 构建查询条件，参考 testBoolSearch 方法的逻辑
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("name", keyword).analyzer("ik_smart"))
                .should(QueryBuilders.termQuery("category", keyword))
                .should(QueryBuilders.termQuery("brand", keyword))
                .minimumShouldMatch(1);

        sourceBuilder.query(boolQuery);

        // 设置分页大小
        sourceBuilder.size(size);

        // 根据分页方向设置排序字段
        if ("prev".equals(direction)) {
            // 上一页：降序排列
            sourceBuilder.sort("id", org.elasticsearch.search.sort.SortOrder.DESC);
        } else {
            // 下一页：升序排列（默认）
            sourceBuilder.sort("id", org.elasticsearch.search.sort.SortOrder.ASC);
        }

        // 如果有 searchAfter 参数，则设置
        if (searchAfter != null && !searchAfter.isEmpty()) {
            sourceBuilder.searchAfter(new Object[]{searchAfter});
        }

        request.source(sourceBuilder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        List<ItemDoc> itemDocs = new ArrayList<>();

        // 处理查询结果
        Object[] lastSortValues = null;
        Object[] firstSortValues = null;
        
        SearchHit[] searchHits = hits.getHits();
        
        // 如果是查询上一页，需要反转结果顺序
        if ("prev".equals(direction) && searchHits.length > 0) {
            // 反转数组
            for (int i = searchHits.length - 1; i >= 0; i--) {
                SearchHit hit = searchHits[i];
                String json = hit.getSourceAsString();
                ItemDoc itemDoc = JSONUtil.toBean(json, ItemDoc.class);
                itemDocs.add(itemDoc);
                if (i == searchHits.length - 1) {
                    firstSortValues = hit.getSortValues(); // 第一条记录的 sort 值（用于上一页）
                }
                if (i == 0) {
                    lastSortValues = hit.getSortValues(); // 最后一条记录的 sort 值（用于下一页）
                }
            }
        } else {
            // 正常顺序处理
            for (int i = 0; i < searchHits.length; i++) {
                SearchHit hit = searchHits[i];
                String json = hit.getSourceAsString();
                ItemDoc itemDoc = JSONUtil.toBean(json, ItemDoc.class);
                itemDocs.add(itemDoc);
                if (i == 0) {
                    firstSortValues = hit.getSortValues(); // 第一条记录的 sort 值（用于上一页）
                }
                if (i == searchHits.length - 1) {
                    lastSortValues = hit.getSortValues(); // 最后一条记录的 sort 值（用于下一页）
                }
            }
        }

        // 判断是否有上一页：需要额外查询来确定
        boolean hasPrev = false;
        if (searchAfter != null && !searchAfter.isEmpty() && searchHits.length > 0) {
            // 执行一个反向查询来检查是否还有上一页的数据
            SearchRequest prevCheckRequest = new SearchRequest("items");
            SearchSourceBuilder prevCheckBuilder = new SearchSourceBuilder();
            prevCheckBuilder.query(boolQuery);
            prevCheckBuilder.size(1); // 只需要查询1条来判断是否存在
            prevCheckBuilder.sort("id", org.elasticsearch.search.sort.SortOrder.DESC);
            
            // 使用当前页第一条数据的id作为searchAfter来查询上一页
            if (firstSortValues != null && firstSortValues.length > 0) {
                prevCheckBuilder.searchAfter(new Object[]{firstSortValues[0]});
            }
            
            prevCheckRequest.source(prevCheckBuilder);
            
            try {
                SearchResponse prevCheckResponse = client.search(prevCheckRequest, RequestOptions.DEFAULT);
                hasPrev = prevCheckResponse.getHits().getHits().length > 0;
            } catch (Exception e) {
                // 如果查询失败，保守地认为有上一页
                hasPrev = true;
            }
        }

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("items", itemDocs);
        result.put("nextPageAfter", lastSortValues); // 下一页的锚点
        result.put("prevPageAfter", hasPrev ? firstSortValues : null); // 只有确实有上一页时才返回锚点
        result.put("totalHits", hits.getTotalHits().value);
        result.put("hasNext", searchHits.length == size); // 如果返回的数据等于页面大小，可能还有下一页
        result.put("hasPrev", hasPrev); // 通过额外查询确定是否有上一页

        return result;
    }

    @Override
    public PageBean<Item> findHomeItems(Integer pageNum) {
        PageBean<Item> pb = new PageBean<>();
        PageHelper.startPage(pageNum, PAGE_SIZE);
        List<Item> items = itemMapper.findHomeItems(STATUS_ON_SALE);
        //强转的原因：Page中提供了方法，可以获取总记录数和当前页数据
        Page<Item> p = (Page<Item>) items;
        //把数据填充到PageBean对象中
        pb.setTotal(p.getTotal());
        pb.setItems(p.getResult());
        return pb;
    }

    @Override
    public void reduceStock(Long itemId, Long num) {
        itemMapper.reduceStock(itemId, num);
    }

    @Override
    public void reduceStockBatch(List<Cart> cartList) {
        itemMapper.reduceStockBatch(cartList);
    }

    @Override
    public void addStock(DetailOrder detailOrder) {
        itemMapper.addStock(detailOrder);
    }

    @Override
    public void addStocks(List<DetailOrder> detailOrders) {
        itemMapper.addStocks(detailOrders);
    }

    @Override
    public void disableItemsByMerchantId(Long merchantId) {
        itemMapper.disableItemsByMerchantId(merchantId);
        List<Long> itemIds = itemMapper.getItemsIdsByMerchantId(merchantId);
        if(itemIds != null) {
            cartService.disableCartItems(itemIds);
        }
    }

    @Override
    public void enableItemsByMerchantId(Long merchantId) {
        itemMapper.enableItemsByMerchantId(merchantId);
    }

    @Override
    public void disableItem(Long itemId) throws IOException {
        itemMapper.disableItem(itemId);
        cartService.disableCartItem(itemId);
        //从Elasticsearch中删除该商品
        DeleteRequest request = new DeleteRequest();
        request.index("items").id(itemId.toString());
        client.delete(request, RequestOptions.DEFAULT);
    }

    @Override
    public void updateItem(Item item) throws IOException {
        itemMapper.updateItem(item);
        cartMapper.disableCartItem(item.getId());
        //从Elasticsearch中删除该商品
        DeleteRequest request = new DeleteRequest();
        request.index("items").id(item.getId().toString());
        client.delete(request, RequestOptions.DEFAULT);
    }

    @Override
    public void deleteItem(Long itemId) throws IOException {
        itemMapper.deleteItem(itemId);
        cartMapper.deleteByCartId(itemId);
        // 从Elasticsearch中删除该商品
        DeleteRequest request = new DeleteRequest();
        request.index("items").id(itemId.toString());
        client.delete(request, RequestOptions.DEFAULT);
    }

    @Override
    public void deleteItems(List<Long> itemIds) throws IOException {
        itemMapper.deleteItems(itemIds);
        cartMapper.disableCartItems(itemIds);
        // 在Elasticsearch中批量删除数据
        BulkRequest request = new BulkRequest();

        for (Long itemId : itemIds){
            request.add(new DeleteRequest().index("items").id(itemId.toString()));
        }

        client.bulk(request, RequestOptions.DEFAULT);
    }

    @Override
    public void disableItems(List<Long> itemIds) throws IOException {
        cartService.disableCartItems(itemIds);
        itemMapper.disableItems(itemIds);
        // 在Elasticsearch中批量删除数据
        BulkRequest request = new BulkRequest();

        for (Long itemId : itemIds){
            request.add(new DeleteRequest().index("items").id(itemId.toString()));
        }

        client.bulk(request, RequestOptions.DEFAULT);
    }

    @Override
    public List<Item> getBestSellingItems() {
        return itemMapper.getBestSellingItems();
    }

    @Override
    public void enableItem(Long itemId) {
        itemMapper.enableItem(itemId);
    }

    @Override
    public void enableItems(List<Long> itemIds) {
        itemMapper.enableItems(itemIds);
    }

    @Override
    public List<Long> findItemsIdByMerchantId(Long merchantId) {
        return itemMapper.getItemsIdsByMerchantId(merchantId);
    }

    @Override
    public List<Item> findItemsByIds(List<Long> itemIds) {
        return itemMapper.findItemsByIds(itemIds);
    }


}
